"""
认证中间件模块
提供API访问的身份验证功能
"""
import os
import jwt
from functools import wraps
from flask import request, current_app

from api.utils.response_utils import unauthorized_response, forbidden_response

def token_required(f):
    """
    JWT令牌验证装饰器
    
    Args:
        f: 要装饰的函数
        
    Returns:
        装饰后的函数
    """
    @wraps(f)
    def decorated(*args, **kwargs):
        token = None
        
        # 从请求头获取令牌
        auth_header = request.headers.get('Authorization')
        if auth_header and auth_header.startswith('Bearer '):
            token = auth_header.split(' ')[1]
        
        # 如果没有令牌，尝试从查询参数获取
        if not token:
            token = request.args.get('token')
        
        # 开发环境可以使用简单的API密钥验证
        # 注意：这只是为了开发方便，生产环境应该使用完整的JWT验证
        api_key = request.args.get('api_key') or request.headers.get('X-API-Key')
        
        # 对于开发环境，允许没有认证（可选）
        if current_app.config.get('DEBUG', False):
            # 开发模式下，如果没有提供认证，也允许访问
            if not token and not api_key:
                current_app.logger.warning('No authentication provided in debug mode')
                return f(*args, **kwargs)
        
        # 如果是简单的API密钥验证（开发模式）
        if api_key:
            # 在实际项目中，应该从数据库或配置中验证API密钥
            valid_api_keys = current_app.config.get('VALID_API_KEYS', [])
            
            # 简单的开发模式API密钥检查
            if api_key == current_app.config.get('DEV_API_KEY', 'dev_key') or api_key in valid_api_keys:
                # 在kwargs中添加用户信息
                kwargs['user_info'] = {
                    'auth_type': 'api_key',
                    'api_key': api_key
                }
                return f(*args, **kwargs)
            else:
                return unauthorized_response('Invalid API key')
        
        # 如果提供了JWT令牌，进行验证
        if token:
            try:
                # 开发环境允许使用dummy_token
                if token == 'dummy_token':
                    # 为dummy_token提供基本的用户信息
                    kwargs['user_info'] = {
                        'auth_type': 'dummy',
                        'user_id': 'dummy_user',
                        'username': '开发用户',
                        'role': 'admin'
                    }
                    return f(*args, **kwargs)
                
                # 解码JWT令牌
                secret_key = current_app.config.get('SECRET_KEY', 'your_secret_key')
                algorithm = current_app.config.get('JWT_ALGORITHM', 'HS256')
                
                payload = jwt.decode(token, secret_key, algorithms=[algorithm])
                
                # 在kwargs中添加用户信息
                kwargs['user_info'] = {
                    'auth_type': 'jwt',
                    'user_id': payload.get('user_id'),
                    'username': payload.get('username'),
                    'role': payload.get('role', 'user'),
                    'payload': payload
                }
                
                return f(*args, **kwargs)
                
            except jwt.ExpiredSignatureError:
                return unauthorized_response('Token has expired')
            except jwt.InvalidTokenError:
                return unauthorized_response('Invalid token')
            except Exception as e:
                current_app.logger.error(f"Token validation error: {str(e)}")
                return unauthorized_response('Authentication error')
        
        # 如果没有提供有效的认证
        return unauthorized_response('Authentication required')
    
    return decorated

def role_required(required_role):
    """
    角色验证装饰器
    
    Args:
        required_role: 所需的角色
        
    Returns:
        装饰后的函数
    """
    def decorator(f):
        @wraps(f)
        def decorated(*args, **kwargs):
            # 确保先进行令牌验证
            if 'user_info' not in kwargs:
                return unauthorized_response('Authentication required')
            
            user_info = kwargs['user_info']
            user_role = user_info.get('role', 'user')
            
            # 检查角色是否满足要求
            # 简单的角色层级：admin > manager > user
            role_hierarchy = {
                'admin': ['admin', 'manager', 'user'],
                'manager': ['manager', 'user'],
                'user': ['user']
            }
            
            if required_role not in role_hierarchy or user_role not in role_hierarchy[required_role]:
                return forbidden_response('Insufficient permissions')
            
            return f(*args, **kwargs)
        
        return decorated
    
    return decorator

def admin_required(f):
    """
    管理员权限验证装饰器
    
    Args:
        f: 要装饰的函数
        
    Returns:
        装饰后的函数
    """
    return role_required('admin')(f)

def manager_required(f):
    """
    管理员或经理权限验证装饰器
    
    Args:
        f: 要装饰的函数
        
    Returns:
        装饰后的函数
    """
    return role_required('manager')(f)

def generate_token(user_id, username, role='user', expires_in=None):
    """
    生成JWT令牌
    
    Args:
        user_id: 用户ID
        username: 用户名
        role: 用户角色
        expires_in: 过期时间（秒）
        
    Returns:
        str: JWT令牌
    """
    import datetime
    
    # 设置过期时间
    if expires_in:
        expiration = datetime.datetime.utcnow() + datetime.timedelta(seconds=expires_in)
    else:
        # 默认过期时间：24小时
        expiration = datetime.datetime.utcnow() + datetime.timedelta(days=1)
    
    # 创建payload
    payload = {
        'user_id': user_id,
        'username': username,
        'role': role,
        'exp': expiration,
        'iat': datetime.datetime.utcnow()
    }
    
    # 生成令牌
    secret_key = current_app.config.get('SECRET_KEY', 'your_secret_key')
    algorithm = current_app.config.get('JWT_ALGORITHM', 'HS256')
    
    token = jwt.encode(payload, secret_key, algorithm=algorithm)
    
    # 如果是字节类型，转换为字符串
    if isinstance(token, bytes):
        token = token.decode('utf-8')
    
    return token

def verify_token(token):
    """
    验证JWT令牌
    
    Args:
        token: JWT令牌
        
    Returns:
        dict: 令牌载荷，如果验证失败返回None
    """
    try:
        secret_key = current_app.config.get('SECRET_KEY', 'your_secret_key')
        algorithm = current_app.config.get('JWT_ALGORITHM', 'HS256')
        
        payload = jwt.decode(token, secret_key, algorithms=[algorithm])
        return payload
        
    except Exception as e:
        current_app.logger.error(f"Token verification error: {str(e)}")
        return None

def get_current_user():
    """
    获取当前请求的用户信息
    
    Returns:
        dict: 用户信息，如果未认证返回None
    """
    # 从请求上下文获取令牌
    token = None
    auth_header = request.headers.get('Authorization')
    if auth_header and auth_header.startswith('Bearer '):
        token = auth_header.split(' ')[1]
    
    if not token:
        token = request.args.get('token')
    
    if token:
        return verify_token(token)
    
    return None

def check_basic_auth(username, password):
    """
    检查基本认证
    
    Args:
        username: 用户名
        password: 密码
        
    Returns:
        bool: 认证是否通过
    """
    # 从配置或环境变量获取有效的用户名密码
    valid_username = current_app.config.get('BASIC_AUTH_USERNAME', 'admin')
    valid_password = current_app.config.get('BASIC_AUTH_PASSWORD', 'password')
    
    # 在实际项目中，应该使用更安全的密码验证方式
    return username == valid_username and password == valid_password

# 导出
__all__ = [
    'token_required',
    'role_required',
    'admin_required',
    'manager_required',
    'generate_token',
    'verify_token',
    'get_current_user',
    'check_basic_auth'
]